/*
Copyright 2011 Raymond Giorgi

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */

package edu.pitt.cs3530.objects.utilization;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;

/**
 * This class stores the information read in from /proc/stat. The variable names
 * are the ones used in the Linux command 'top'
 * 
 * @author NoOne
 * 
 */
public class StatFactory {

	public static class UtilizationStat {
		private int us;
		private int sy;
		private int ni;
		private int idle;
		private int wa;
		private int hi;
		private int si;
		private int st;

		/**
		 * 
		 * @param us
		 * @param sy
		 * @param ni
		 * @param idle
		 * @param wa
		 * @param hi
		 * @param si
		 * @param st
		 */
		private UtilizationStat(int us, int sy, int ni, int idle, int wa,
				int hi, int si, int st) {
			this.us = us;
			this.sy = sy;
			this.ni = ni;
			this.idle = idle;
			this.wa = wa;
			this.hi = hi;
			this.si = si;
			this.st = st;
		}

		public UtilizationStat getDifference(UtilizationStat stat) {
			int tus = us - stat.us;
			int tsy = sy - stat.sy;
			int tni = ni - stat.ni;
			int tidle = idle - stat.idle;
			int twa = wa - stat.wa;
			int thi = hi - stat.hi;
			int tsi = si - stat.si;
			int tst = st - stat.st;
			return new UtilizationStat(tus, tsy, tni, tidle, twa, thi, tsi, tst);
		}

		public int getTotal(UtilizationStat stat) {
			return stat.us + stat.sy + stat.ni + stat.idle + stat.wa + stat.hi
					+ stat.si + stat.st;
		}

		public double getIdlePercent() {
			int total = getTotal(this);
			return (double) this.idle / (double) total;
		}

		public double getUsedPercent() {
			return ((double) this.us + (double) this.sy) / getTotal(this);
		}

		public double getBlockedPercent() {
			return ((double) this.wa) / (double) getTotal(this);
		}

		/**
		 * 
		 * @param stat
		 * @return the absolute utilization as a percentage of the whole
		 */
		public double getUtilization(UtilizationStat stat) {
			UtilizationStat diff = getDifference(stat);
			int total = getTotal(diff);
			return (double) (total - diff.idle) / (double) (total);
		}

		public double getIdle(UtilizationStat stat) {
			UtilizationStat diff = getDifference(stat);
			int total = getTotal(diff);
			return (double) (diff.idle) / (double) (total);
		}

		public double getBlocked(UtilizationStat stat) {
			UtilizationStat diff = getDifference(stat);
			int total = getTotal(diff);
			return (double) (diff.wa) / (double) (total);
		}
	}

	public static UtilizationStat createStat() throws IOException {
		BufferedReader reader = new BufferedReader(new FileReader("/proc/stat"));
		StringTokenizer statTok = new StringTokenizer(reader.readLine(), " ");
		statTok.nextToken();
		return new UtilizationStat(Integer.parseInt(statTok.nextToken()),
				Integer.parseInt(statTok.nextToken()), Integer.parseInt(statTok
						.nextToken()), Integer.parseInt(statTok.nextToken()),
				Integer.parseInt(statTok.nextToken()), Integer.parseInt(statTok
						.nextToken()), Integer.parseInt(statTok.nextToken()),
				Integer.parseInt(statTok.nextToken()));
	}
}
